home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks96 / RoasterJavaWAHTTPCGI.sit / Roaster-Java-WA-HTTP-CGI hack / Protect WA plugin / Protect.cp < prev    next >
Text File  |  1996-06-22  |  18KB  |  646 lines

  1. // Sample field protection plugin, using the industry standart ROT13 algorithm.
  2.  
  3.  
  4. #include "ArrangeCallbacks.h"
  5. #include "PluginLibrary.h"
  6.  
  7. #include <Dialogs.h>
  8. #include <StandardFile.h>
  9. #include <string.h>
  10. #include <Folders.h>
  11. #include <TextUtils.h>
  12. #include <Resources.h>
  13. #include <AppleEvents.h>
  14. #include <PLStringFuncs.h>        /* some special string handling stuff */
  15.  
  16. #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
  17.     #include "A4Stuff.h"
  18. #endif
  19.  
  20. #define ModuleRsrcID -0x8000
  21.  
  22. #define OurModuleID    0x72300000        //Unique module ID assigned by Phil Meyer
  23. //#define OurModuleID  0x70001513  // Unique module ID; replace with a value
  24.                                            // obtained from Common Knowledge.
  25. #define baseCmdCode  OurModuleID
  26.  
  27. #define pluginName    "Protect" // controls our name in the About menu
  28. #define aboutCmdCode (baseCmdCode + 0)
  29. #define reformatText (baseCmdCode + 1)
  30.  
  31. #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
  32.     #define SetupA4            long    lOldA4 = SetCurrentA4 ();
  33.     #define TearDownA4         SetA4 (lOldA4);
  34.     #define UnloadSegs        UnloadSegsFunc ();
  35.  
  36.     static void UnloadSegsFunc ();
  37. #else
  38.     #define SetupA4
  39.     #define TearDownA4
  40.     #define UnloadSegs
  41. #endif    //__MWERKS__
  42.  
  43. typedef struct {
  44.         const ArrangeCallbackTbl* calls;
  45.     } myprefs;
  46.  
  47. class Plugin
  48.     {
  49. public:
  50.     Plugin(const ArrangeCallbackTbl* theCalls);
  51.     ~Plugin();
  52.     
  53.     arHookResult ClickNotify( arClickLocation loc, Point where, Short modifiers,
  54.                                       Short clickCount, arNoteID note, arFieldID field,
  55.                                       arPathID path );
  56.     arHookResult KeyNotify  ( Short theChar, Short key, Short modifiers );
  57.     arHookResult MenuNotify ( Integer commandCode, Integer commandParam,
  58.                                       Short modifiers );
  59.     void AboutToMenu();
  60.     arHookResult FieldNotify( arNoteID note, arFieldID field, arFieldAction action,
  61.                                       const char* choiceText );
  62.     void         TopicNotify( arTopicID newTopic, arWindowID newWindow,
  63.                                       arTopicAction action );
  64.     void             TickNotify (  );
  65.     arHookResult FileNotify ( arFileAction action );
  66.     arHookResult QuitNotify (  );
  67.     void         ATMNotify  (  );
  68.     void             FormatTheNotes (  );
  69.     
  70. private:
  71.     const ArrangeCallbackTbl* calls; // callback table
  72.     myprefs    theprefs;
  73.     }; // Plugin
  74.  
  75.  
  76. /*************************************************************************/
  77. /**************************** Main entry point ***************************/
  78. /*************************************************************************/
  79.  
  80. /* Root entry point for the module - must be the first function in the
  81.  * file, so that the linker will place it first in the code segment.
  82.  * This is the routine which Arrange calls at application startup time
  83.  * (and again at quit time).
  84.  * 
  85.  * Most plug-ins will not need to modify this routine or the Hook functions
  86.  * immediately following.  All customization can be done in the "Plugin"
  87.  * section (below).
  88.  */
  89. extern "C" Integer main( ModuleParamBlock *pb, pModuleRootAction action,
  90.                                             Integer /*p1*/ )
  91.     {
  92.     SetupA4;
  93.  
  94.     Integer    lResult = 0;
  95.  
  96.     /* Extract the callback table from our parameter block, and coerce it
  97.      * to the extended Arrange table.
  98.      */
  99.     ArrangeCallbackTbl* calls = (ArrangeCallbackTbl*)(pb->calls);
  100.     
  101.     Assert (sizeof (Byte) == 1);
  102.     Assert (sizeof (Short) == 2);
  103.     Assert (sizeof (Integer) == 4);
  104.     Assert (sizeof (Float) == 8);
  105.  
  106.     switch (action)
  107.         {
  108.         case mrLoad:
  109.             {
  110.             // Allocate memory and create a new Plugin object.
  111.             void* storage = calls->mem->AllocMem( sizeof(Plugin),
  112.                                                               amFreeStore | amErrIfNoMem );
  113.             pb->moduleRefcon = uInteger(new(storage) Plugin(calls));
  114.             lResult = 1;
  115.             }
  116.             break;
  117.         
  118.         case mrUnload:
  119.             {
  120.             /* Dispose of the Plugin object and release the memory
  121.              * it occupies.
  122.              */
  123.             delete (Plugin*)(pb->moduleRefcon);
  124.             calls->mem->DeallocMem((void*)(pb->moduleRefcon), amFreeStore);
  125.             lResult = 0;
  126.             }
  127.             break;
  128.         
  129.         case mrFindEntry:
  130.         default:
  131.             {
  132.             /* This module contains no extended entry points, so we always
  133.              * return 0 for the mrFindEntry message.  Most plug-ins will not
  134.              * use extended entry points.
  135.              */
  136.             lResult = 0;
  137.             }
  138.             break;
  139.         
  140.         } // switch (action)
  141.     
  142.     TearDownA4;
  143.     return lResult;
  144.     } // main
  145.  
  146. #if defined (__MWERKS__) && defined (PLUGIN_GLOBALS)
  147. #pragma segment PluginLib
  148. static void PluginLibSeg (void)
  149. {
  150. }
  151.  
  152. #pragma segment Main
  153. static void UnloadSegsFunc ()
  154. {
  155.     // Put segment unloading code here.
  156.     // Do NOT use UnloadSeg!
  157.     //UnloadA4Seg (PluginLibSeg);
  158. }
  159. #endif    //__MWERKS__ && PLUGIN_GLOBALS
  160.  
  161. /* These hook functions simply pass control to the appropriate function
  162.  * in the Plugin object.
  163.  */
  164. static arHookResult OurClickHook( ModuleParamBlock* pb, arClickLocation loc,
  165.                                              Point where, pShort modifiers, pShort clickCount,
  166.                                              arNoteID note, arFieldID field,
  167.                                              arPathID path ENDP )
  168.     {
  169.     SetupA4;
  170.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->ClickNotify( loc, where, modifiers,
  171.                                                                         clickCount, note, field,
  172.                                                                         path );
  173.     TearDownA4;
  174.     return eResult;
  175.     }
  176.  
  177.  
  178. static arHookResult OurKeyHook( ModuleParamBlock* pb, pShort theChar, pShort key,
  179.                                           pShort modifiers ENDP )
  180.     {
  181.     SetupA4;
  182.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->KeyNotify(theChar, key, modifiers);
  183.     TearDownA4;
  184.     return eResult;
  185.     }
  186.  
  187.  
  188. static arHookResult OurMenuHook( ModuleParamBlock* pb, Integer commandCode,
  189.                                             Integer commandParam, pShort modifiers ENDP )
  190.     {
  191.     SetupA4;
  192.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->MenuNotify( commandCode, commandParam,
  193.                                                                      modifiers );
  194.     TearDownA4;
  195.     return eResult;
  196.     }
  197.  
  198.  
  199. void OurATMHook(ModuleParamBlock* pb)
  200.     {
  201.     ((Plugin*)(pb->moduleRefcon))->AboutToMenu();
  202.     } // OurATMHook
  203.  
  204.  
  205. static arHookResult OurFieldHook( ModuleParamBlock* pb, arNoteID note,
  206.                                              arFieldID field, arFieldAction action,
  207.                                              const char* choiceText ENDP )
  208.     {
  209.     SetupA4;
  210.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->FieldNotify( note, field, action,
  211.                                                                         choiceText );
  212.     TearDownA4;
  213.     return eResult;
  214.     }
  215.  
  216.  
  217. static void OurTopicHook( ModuleParamBlock* pb, arTopicID newTopic,
  218.                                   arWindowID newWindow, arTopicAction action ENDP )
  219.     {
  220.     SetupA4;
  221.     ((Plugin*)(pb->moduleRefcon))->TopicNotify(newTopic, newWindow, action);
  222.     TearDownA4;
  223.     }
  224.  
  225.  
  226. static void OurTickHook(ModuleParamBlock* pb ENDP)
  227.     {
  228.     SetupA4;
  229.     ((Plugin*)(pb->moduleRefcon))->TickNotify();
  230.     TearDownA4;
  231.     }
  232.  
  233.  
  234. static arHookResult OurFileHook(ModuleParamBlock* pb, arFileAction action ENDP)
  235.     {
  236.     SetupA4;
  237.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->FileNotify(action);
  238.     TearDownA4;
  239.     return eResult;
  240.     }
  241.  
  242.  
  243. static arHookResult OurQuitHook(ModuleParamBlock* pb ENDP)
  244.     {
  245.     SetupA4;
  246.     arHookResult    eResult = ((Plugin*)(pb->moduleRefcon))->QuitNotify();
  247.     TearDownA4;
  248.     return eResult;
  249.     }
  250.  
  251. /*************************************************************************/
  252. /********************************* Plugin ********************************/
  253. /*************************************************************************/
  254.  
  255. /* Construct a Plugin object.  This is called once, from the OurModuleRoot
  256.  * function, when the module is initialized (i.e. at application startup time).
  257.  */
  258. Plugin::Plugin(const ArrangeCallbackTbl* theCalls)
  259.     {
  260.     short    thelength;
  261.     arDocumentPtr    theCurDoc;
  262.     arDocumentPtr    thePrefDoc;
  263.     Str255            ourname;
  264.     Handle            temph;
  265.     
  266.     // Record the callback table for future use.
  267.     calls = theCalls;
  268.     
  269.     /* These commands, if un-commented-out, register this plugin to be called
  270.      * by Arrange when various events occur.  For example, if you un-comment-out
  271.      * the call to SetClickHook, then Plugin::ClickNotify will be called
  272.      * whenever the user clicks in any of the locations described in the
  273.      * arClickLocation enum.
  274.      */
  275.     // calls->ui->SetClickHook(OurClickHook, 0, true);
  276.     // calls->ui->SetKeyHook  (OurKeyHook,   0, true, charFilter, keyFilter, modFilter);
  277.     // calls->ui->SetMenuHook (OurMenuHook,  0, true, whichCommand);
  278.     // calls->ui->SetFieldHook(OurFieldHook, 0, true, whichField);
  279.     //calls->ui->SetTopicHook(OurTopicHook, 0, true);
  280.     // calls->ui->SetFileHook (OurFileHook,  0, true);
  281.     //calls->ui->SetQuitHook (OurQuitHook,  0, true);
  282.     calls->ui->SetTickHook (OurTickHook,  0, true);
  283.     calls->ui->SetATMHook  (OurATMHook,   0, true);
  284.     
  285.     // Add an item to the About Plugins menu for this plugin.
  286.     temph = GetResource('STR ', ModuleRsrcID+1); // "About Protect"
  287.     BlockMove ((Ptr)*temph, (Ptr)(&ourname), 50);
  288.     ourname[ourname[0]+1] = 0; //Make good for C String
  289.     calls->ui->AddMenuItem(mPluginAbout,  (char *)(&ourname[1]), 0, aboutCmdCode, 1);
  290.     
  291.     temph = GetResource('STR ', ModuleRsrcID+2); // "Protect Text"
  292.     BlockMove ((Ptr)*temph, (Ptr)(&ourname), 50);
  293.     ourname[ourname[0]+1] = 0; //Make good for C String
  294.     calls->ui->AddMenuItem(mEdit, (char *)(&ourname[1]),     0, reformatText,    2);    
  295.     
  296.     calls->ui->SetMenuHook(OurMenuHook, 1, true, aboutCmdCode);
  297.     calls->ui->SetMenuHook(OurMenuHook, 2, true, reformatText);
  298.     
  299.     } // Plugin constructor
  300.  
  301.  
  302. /* Dispose of a Plugin object.  This is called when Arrange terminates.  You
  303.  * should free up any data structures which you allocation in the Plugin
  304.  * constructor (above).
  305.  */
  306. Plugin::~Plugin()
  307.     {
  308.     } // ~Plugin
  309.  
  310.  
  311. /* This function is called whenever the user clicks in an "interesting place"
  312.  * in a document window.  It should return true if we handle the click, false
  313.  * (the normal case) when the click should be passed along to other plug-ins
  314.  * or to Arrange's normal event processing.  See the documentation for
  315.  * SetClickHook for more details.
  316.  */
  317. arHookResult Plugin::ClickNotify( arClickLocation loc, Point where,
  318.                                              Short modifiers, Short clickCount,
  319.                                              arNoteID note, arFieldID field,
  320.                                              arPathID path )
  321.     {
  322.     return false; // Let Arrange handle the event
  323.     } // ClickNotify
  324.  
  325.  
  326. /* This function is called whenever the user types a key which matches the
  327.  * filters we pass to SetKeyHook in Plugin's constructor.  It should return
  328.  * true if we handle the event, false (the normal case) when the event
  329.  * should be passed along to other plug-ins or to Arrange's normal event
  330.  * processing.  See the documentation for SetKeyHook for more details.
  331.  */
  332. arHookResult Plugin::KeyNotify(Short theChar, Short key, Short modifiers)
  333.     {
  334.     return false; // Let Arrange handle the event
  335.     } // KeyNotify
  336.  
  337. // OK, we get the notes, get their text, and do cool stuff with them!
  338.  
  339. static Boolean ProtectText(const ArrangeCallbackTbl* calls, Ptr theptr, short* thelength)
  340. {
  341.     Ptr    p;
  342.     char    lastChar=0;
  343.     char    thechar=0xff;
  344.     char    x;
  345.     
  346.     char key[256];
  347.     
  348.     calls->dlg->PromptForString("Enter password", key, 255, false);
  349.     
  350.     short l = *thelength;
  351.     
  352.     p=theptr;
  353.     Boolean    IsChanged = false;
  354.     
  355.  
  356.     while (l-- > 0)
  357.     {
  358.         if (*p >= 'A' && *p <= 'Z')
  359.         {
  360.             x = (*p - 'A');
  361.             x = (x + 13) % 26;
  362.             
  363.             *p = 'A' + (x);
  364.             IsChanged = true;
  365.         }
  366.         
  367.         if (*p >= 'a' && *p <= 'z')
  368.         {
  369.             x = (*p - 'a');
  370.             x = (x + 13) % 26;
  371.             
  372.             *p = 'a' + (x);
  373.             IsChanged = true;
  374.         }
  375.         
  376.         p++;
  377.     }
  378.  
  379.     return IsChanged;
  380. }
  381.  
  382. void    Plugin::FormatTheNotes (  )
  383. {
  384.     Integer        i;    
  385.     short    whichnote;
  386.     // Determine whether there is a selection and how many notes it contains.
  387.     Integer selCount;
  388.     
  389.     arNoteID  selNote;
  390.     arNoteID     parentNote;
  391.     arFieldID selField;
  392.     Integer   selStart;
  393.     Integer   selEnd;
  394.     
  395.     short        thecount;
  396.     arFieldID    theField;
  397.     arFieldInfo info;
  398.     arNoteInfo    thetopicinfo;
  399.     short    thelength;
  400.     Str255    tempstr;
  401.     Ptr        theptr;
  402.     char        TheName[32]="Protecting";
  403.     Boolean    firstchange = true;
  404.     
  405.     Str31 promptstr = "Now protecting";
  406.     Handle    temph;
  407.     
  408.     temph = GetResource('STR ', ModuleRsrcID+3); // "Now Reformatting Text"
  409.     BlockMove((Ptr)*temph, &promptstr, 32);
  410.     
  411.     promptstr[promptstr[0]+1] = 0;
  412.     
  413.     calls->dlg->DisplayNotify( (const char*)&promptstr[1], nfShowImmediately);
  414.     
  415.     if (!calls->sel->FlushSelection(false))
  416.     {
  417.         calls->dlg->ClearNotify();
  418.         return;
  419.     }
  420.  
  421.     switch (calls->sel->GetSelection(&selNote, &selField, &selStart, &selEnd))
  422.         {
  423.         case stNote:
  424.         case stFieldContents:
  425.             selCount = 1;
  426.             break;
  427.         
  428.         case stMultipleNotes:
  429.         case stMultipleFields:
  430.             selCount = selStart;
  431.             break;
  432.         
  433.         case stField:
  434.                 thelength = calls->data->GetFieldTextLen(selNote, selField);
  435.                 if (thelength)
  436.                 {
  437.                     info.versNum = 1;
  438.                     calls->sysObj->GetFieldInfo(selField, &info);
  439.                     thelength = calls->data->GetFieldTextLen(selNote, selField);
  440.                     if (thelength)
  441.                     {
  442.                         theptr = NewPtr(thelength+1);
  443.                         if (!theptr)
  444.                         {
  445.                             calls->dlg->ClearNotify();
  446.                             return;
  447.                         }
  448.                         thelength = calls->data->GetFieldText(selNote, selField, thelength+1,  (char*)theptr);
  449.                         if (ProtectText(calls, theptr, &thelength))
  450.                         {
  451.                             if (firstchange)
  452.                             {
  453.                                 calls->doc->SetupUndo(TheName, true);
  454.                                 firstchange = false;
  455.                             }
  456.  
  457.                             calls->data->SetFieldText(selNote, selField, (char*)theptr, thelength, 0);
  458.                             calls->sel->FlushSelection(false);
  459.                         }
  460.                         DisposePtr(theptr);
  461.                     }
  462.                 }
  463.                 calls->dlg->ClearNotify();
  464.                 return;
  465.                 break;
  466.         case stText:  // selected text is treated specially
  467.                 thelength = calls->data->GetFieldTextLen(selNote, selField);
  468.                 if (thelength)
  469.                 {
  470.                     theptr = NewPtr(thelength+1);
  471.                     if (!theptr)
  472.                     {
  473.                         calls->dlg->ClearNotify();
  474.                         return;
  475.                     }
  476.                     thelength = calls->sel->GetSelText(thelength+1,  (char*)theptr, &selStart, &selEnd);
  477.                     thelength = selEnd-selStart;
  478.                     *((Ptr)(theptr+selEnd+1)) = 0;
  479.                     if (ProtectText(calls, (Ptr)(theptr+selStart), &thelength))
  480.                     {
  481.                         calls->sel->ReplaceSelText((Ptr)(theptr+selStart), TheName);
  482.                         calls->sel->FlushSelection(false);
  483.                     }
  484.                     DisposePtr(theptr);
  485.                 }
  486.                 calls->dlg->ClearNotify();
  487.                 return;
  488.                 break;
  489.         default:
  490.             calls->dlg->ClearNotify();
  491.             return;
  492.         
  493.         } // switch (GetSelection result)
  494.     
  495.     // Iterate over each selected note.
  496.     for (whichnote=0; whichnote<selCount; whichnote++)
  497.         {
  498.             calls->sel->GetSelEntry(whichnote, &selNote, &selField, &parentNote);
  499.             if (selNote != nil)
  500.             {
  501.                 calls->notes->GetNoteInfo(selNote, &thetopicinfo);
  502.                 thecount = calls->notes->CountNoteFields(selNote);
  503.                 for (i=0; i<thecount; i++)
  504.                 {
  505.                     theField = calls->notes->GetNoteField(selNote, i);
  506.                     if (theField!=nil)
  507.                     {
  508.                         info.versNum = 1;
  509.                         calls->sysObj->GetFieldInfo(theField, &info);
  510.                         if (info.type==arFTText)
  511.                         {
  512.                             thelength = calls->data->GetFieldTextLen(selNote, theField);
  513.                             if (thelength)
  514.                             {
  515.                                 theptr = NewPtr(thelength+1);
  516.                                 if (!theptr)
  517.                                 {
  518.                                     calls->dlg->ClearNotify();
  519.                                     return;
  520.                                 }
  521.                                 thelength = calls->data->GetFieldText(selNote, theField, thelength+1,  (char*)theptr);
  522.                                 if (ProtectText(calls, theptr, &thelength))
  523.                                 {
  524.                                     if (firstchange)
  525.                                     {
  526.                                         calls->doc->SetupUndo(TheName, true);
  527.                                         firstchange = false;
  528.                                     }
  529.         
  530.                                     calls->data->SetFieldText(selNote, theField, (char*)theptr, thelength, 0);
  531.                                     calls->sel->FlushSelection(false);
  532.                                 }
  533.                                 DisposePtr(theptr);
  534.                             }
  535.                         }
  536.                     }
  537.                 }
  538.             }
  539.  
  540.         } // whichnote loop
  541.     calls->dlg->ClearNotify();
  542.     return;
  543. }
  544.  
  545. /* This function is called whenever the user clicks in the menu bar or types
  546.  * a command key, just before processing the event.  It does any fixing up
  547.  * of menus which might be necessary based on the current state of affairs.
  548.  */
  549. void Plugin::AboutToMenu()
  550. {
  551.     arNoteID selNote;
  552.     arFieldID selField;
  553.     Integer selStart,selEnd;
  554.     arSelType selType = calls->sel->GetSelection( &selNote, &selField,
  555.                                                                 &selStart, &selEnd );
  556.     
  557.     Boolean hasSingleSel = ( selType == stNote || selType == stMultipleNotes || selType == stText || selType == stField );
  558.     
  559.     calls->ui->SetMenuItem(mEdit, reformatText, 2, nil, ((selType == stNote) || (selType == stMultipleNotes) || (selType == stText) || (selType == stField)), 0, 0);
  560.  
  561. }
  562.  
  563. arHookResult Plugin::MenuNotify( Integer commandCode, Integer commandParam,
  564.                                             Short modifiers )
  565.     {
  566.     ProcessSerialNumber thepsn;
  567.     arTopicID    thistopic;
  568.     arTopicInfo    topicinfo;
  569.     
  570.     /* If this is our About menu item, display our about-box dialog and return
  571.      * true to indicate we handled the command.
  572.      */
  573.     if (commandCode == aboutCmdCode)
  574.         {
  575.         Alert(ModuleRsrcID, nil);
  576.         return true;
  577.         }
  578.     if (commandCode == reformatText)
  579.         {
  580.         FormatTheNotes();
  581.         return true;
  582.         }
  583.     return false; // Let Arrange handle the event
  584.     
  585.     } // MenuNotify
  586.  
  587.  
  588. /* If we register to recieve events for a field by calling SetFieldHook, this
  589.  * function will be called for any events in that field.  It should return
  590.  * false in almost all cases.  See the documentation for SetFieldHook for
  591.  * more details.
  592.  */
  593. arHookResult Plugin::FieldNotify( arNoteID note, arFieldID field,
  594.                                              arFieldAction action, const char* choiceText )
  595.     {
  596.     return false;
  597.     } // FieldNotify
  598.  
  599.  
  600. /* This function is called whenever the user switches windows or changes
  601.  * the current folder/topic/view in the front window.  See the documentation
  602.  * for SetTopicHook for more details.
  603.  */
  604. void Plugin::TopicNotify( arTopicID newTopic, arWindowID newWindow,
  605.                                   arTopicAction action )
  606.     {
  607.     } // TopicNotify
  608.  
  609.  
  610. /* This function is called periodically, whenever Arrange recieves a null
  611.  * event from the Event Manager.
  612.  */
  613. void Plugin::TickNotify()
  614. {
  615. } // TickNotify
  616.  
  617.  
  618. /* This function is called whenever various file-level events occur.  It
  619.  * should return true in almost all cases.  See the documentation for
  620.  * SetFileHook for more details.
  621.  */
  622. arHookResult Plugin::FileNotify(arFileAction action)
  623.     {
  624.     return true;
  625.     } // FileNotify
  626.  
  627.  
  628. /* This function is called if the user voluntarily quits Arrange.  It should
  629.  * return true to allow the user to quit, false to prevent it.  See the
  630.  * documentation for SetQuitHook for more details.
  631.  */
  632. arHookResult Plugin::QuitNotify()
  633.     {
  634.     return true;
  635.     } // QuitNotify
  636.  
  637.  
  638. /* This function is called whenever the user clicks in the menu bar or types
  639.  * a command key, just before processing the event.  It should do any fixing
  640.  * up of menus which might be necessary based on the current state of affairs.
  641.  * See the documentation for SetATMHook for more details.
  642.  */
  643. void Plugin::ATMNotify()
  644.     {
  645.     } // ATMNotify
  646.